package com.chenwc.wso2.wso2mi;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.chenwc.file.Decompression;
import com.chenwc.httpclient.RestMock;
import com.chenwc.wso2.wso2esb.TestWso2EsbMain;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.Socket;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * WSO2 MI 4.2.0
 *
 * @author chenwc
 * @date 2023/9/11 0:20
 */
public class TestWso2MiMain {

    private final static Logger log = LoggerFactory.getLogger(TestWso2EsbMain.class);

    /**
     * WSO2 MI 部署服务器
     */
    private final static String HOST = "192.168.100.149";
    /**
     * 管理API端口，默认9164
     */
    private final static int PORT = 9164;

    /**
     * WSO2 MI 4.2.0 管理api接口地址
     */
    private final static String MGT_API_URL = "https://" + HOST + ":" + PORT + "" + Constants.REST_API_CONTEXT;

    public static void main(String[] args) {
        //上传car包
        File carFile = new File("D:\\Downloads\\USERS.RESPONSE_MSGCompositeExporter_1.0.0-SNAPSHOT.car");
        Map<String, String> carMap = Decompression.getUploadCarbonAppName(carFile);
        log.info(carMap.toString());
        boolean isAvailable = isManagementApiAvailable(HOST, PORT);
        if (isAvailable) {
            log.info("管理 API 可用！");
        } else {
            return;
        }

        String token = getToken("admin", "admin");
        log.info("token: {}", token);

        boolean isExists = retrieveCarbonApplication(token, carMap);
        if (isExists) {
            log.info("WSO2 MI 已存在名称：{}，版本：{} 的工件！", carMap.get("appName"), carMap.get("appVersion"));
            boolean isSuccessRemove = removeCarbonApplication(token, carMap.get("appName") + "_" + carMap.get("appVersion"));
        } else {
            log.info("WSO2 MI 不存在名称：{}，版本：{} 的工件！", carMap.get("appName"), carMap.get("appVersion"));
            boolean isSuccessDeploy = deployCarbonApplication(token, carFile);
        }
    }

    /**
     * 判断car包是否存在
     *
     * @param accessToken token
     * @param carMap      car文件的appName和appVersion
     * @return 是否存在
     */
    public static boolean retrieveCarbonApplication(String accessToken, Map<String, String> carMap) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json");
        headers.put("Authorization", "Bearer ".concat(accessToken));
        String retrieveCarbonApplicationUrl = MGT_API_URL + Constants.PREFIX_CARBON_APPS;
        String rst = RestMock.sendGet(retrieveCarbonApplicationUrl, headers);
        log.info("获取car包列表响应：{}", rst);
        JSONObject rstJson = JSONObject.parseObject(rst);
        int activeCount = rstJson.containsKey("activeCount")
                && StringUtils.isNotEmpty(rstJson.getString("activeCount"))
                ? rstJson.getIntValue("activeCount") : 0;
        if (activeCount > 0) {
            JSONArray activeList = rstJson.getJSONArray("activeList");
            for (int i = 0; i < activeList.size(); i++) {
                JSONObject activeCarbonApp = activeList.getJSONObject(i);
                String name = activeCarbonApp.getString("name");
                String version = activeCarbonApp.getString("version");
                if (name.equals(carMap.get("appName"))
                        && version.equals(carMap.get("appVersion"))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 删除car包
     *
     * @param accessToken token
     * @param carbonApp   car包名称，格式为：名称_版本
     * @return 是否删除成功
     */
    public static boolean removeCarbonApplication(String accessToken, String carbonApp) {

        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json");
        headers.put("Authorization", "Bearer ".concat(accessToken));
        String removeCarbonApplicationUrl = MGT_API_URL + Constants.PREFIX_CARBON_APPS + Constants.ROOT_CONTEXT + carbonApp;
        String rst = RestMock.sendDelete(removeCarbonApplicationUrl, headers);
        log.info("删除car包响应：{}", rst);
        JSONObject rstJson = JSONObject.parseObject(rst);

        return rstJson.containsKey("Message") && StringUtils.isNotEmpty(rstJson.getString("Message"))
                && rstJson.getString("Message").contains("Successfully");
    }


    /**
     * 上传car包
     *
     * @param accessToken token
     * @param carbonApp   car文件
     * @return 是否上传成功
     */
    public static boolean deployCarbonApplication(String accessToken, File carbonApp) {

        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json");
        headers.put("Authorization", "Bearer ".concat(accessToken));
        String deployCarbonApplicationUrl = MGT_API_URL + Constants.PREFIX_CARBON_APPS;
        String rst = RestMock.sendPostByFileAndFormBody(deployCarbonApplicationUrl, headers, null, carbonApp);
        log.info("上传car包响应：{}", rst);
        JSONObject rstJson = JSONObject.parseObject(rst);

        return rstJson.containsKey("Message") && StringUtils.isNotEmpty(rstJson.getString("Message"))
                && rstJson.getString("Message").contains("Successfully");
    }

    /**
     * 获取token
     *
     * @param username 用户名
     * @param password 密码
     * @return token
     */
    public static String getToken(String username, String password) {
        String usernamePassword = username + ":" + password;
        String encodedUsernamePassword = Base64.getEncoder().encodeToString(usernamePassword.getBytes());
        String loginUrl = MGT_API_URL + Constants.PREFIX_LOGIN;

        Map<String, String> header = new HashMap<>();
        header.put("Accept", "application/json");
        header.put("Authorization", "Basic " + encodedUsernamePassword);
        String rest = RestMock.sendGet(loginUrl, header);

        JSONObject jsonObject = JSONObject.parseObject(rest);
        if (jsonObject.containsKey("AccessToken")) {
            return jsonObject.getString("AccessToken");
        } else {
            return "";
        }
    }

    /**
     * 判断管理api是否可用
     *
     * @param host 主机名或者IP地址
     * @param port 端口
     * @return 管理api是否可用
     */
    public static boolean isManagementApiAvailable(String host, int port) {
        try (Socket s = new Socket(host, port)) {
            return true;
        } catch (Exception e) {
            log.error("Error while opening socket for port " + port, e);
            return false;
        }
    }
}
